package com.example.tcp.client;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import com.example.tcp.client.serde.impl.ByteBufMessageSerde;
import com.example.tcp.client.store.IDequeStore;
import com.example.tcp.client.store.StoreFactory;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;
import org.mapdb.DBMaker;
import org.rocksdb.RocksDBException;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.io.IOException;
import java.time.Duration;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;

@Slf4j
public class TcpClientApplication {

    /**
     * 定义加密算法
     */
    private static final String ALGORITHM = "desede";

    /**
     * 加密模式: ECB, 填充模式: 不填充
     */
    private static final String TRANSFORMATION = "DESede/ECB/NoPadding";

    public static String bcd2String(ByteBuf buf){
        StringBuilder temp = new StringBuilder();
        buf.forEachByte(b -> {
            temp.append((byte) ((b & 0xf0) >>> 4));
            temp.append((byte) (b & 0x0f));
            return true;
        });
        return temp.toString();
    }

    public static byte[] hexStringToByteArray(String hex) {
        int l = hex.length();
        byte[] data = new byte[l/2];
        for (int i = 0; i < l; i += 2) {
            data[i/2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i+1), 16));
        }
        return data;
    }

    public static byte[] ees3DecodeECB(byte[] key, byte[] data) throws Exception {
        DESedeKeySpec spec = new DESedeKeySpec(key);
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance(ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, keyfactory.generateSecret(spec));
        return cipher.doFinal(data);
    }

    public static void main(String[] args) throws RocksDBException, IOException {


//        Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
//        root.setLevel(Level.INFO);
//
//        IDequeStore<RetryTcpClient.Message> store = StoreFactory.createBigQueueFileQueueStore("BigQueue", "queue", ByteBufMessageSerde.INSTANCE);
//
//
//        Scanner scanner = new Scanner(System.in);
//
//        System.out.print("enter host: ");
//        String host = scanner.nextLine();
//        System.out.print("enter port: ");
//        int port = scanner.nextInt();
////
////        System.out.print("enter key: ");
////        String key = scanner.nextLine();
////        byte[] desKey = hexStringToByteArray(key.replaceAll("\\s+", ""));
//
//
//        RetryTcpClient client = new RetryTcpClient.Builder()
//                .address(host, port)
//                .connectTimeoutMs((int)Duration.ofSeconds(10).toMillis())
//                .readTimeoutMs(Duration.ofMinutes(4).toMillis())
//                .onChannelInitializer(socketChannel -> {
////                    socketChannel.pipeline().addLast("Decode", new LengthFieldBasedFrameDecoder(2048, 2, 2, -4, 0));
//                })
////                .store(StoreFactory.createMemoryDequeueStore())
////                .store(StoreFactory.createTap2FileQueueStore("Tap2", new Tap2MessageSerde()))
////                .store(StoreFactory.createBigQueueFileQueueStore("BigQueue", "queue", ByteBufMessageSerde.INSTANCE))
////                .store(StoreFactory.createRocksDBFileQueueStore("RocksDB",  "queue", ByteBufMessageSerde.INSTANCE))
////                .store(StoreFactory.createMapDBFileQueueStore("MapDB", new MapDBMessageSerde()))
//                .eventCallback(new RetryTcpClient.EventCallback() {
//                    @Override
//                    public void onConnected(RetryTcpClient client) {
//                        log.info("onConnected");
////                        for(int i = 0;i < 100; ++i) {
////                            client.send(new RetryTcpClient.ByteBufMessage(Unpooled.wrappedBuffer(hexStringToByteArray("5555003538363933373430343030363837343345298C4736BF85218694B41AE4D3CF5F7BA92500DB205D69EF2985DDEE3F7918AAAA"))));
////                        }
//                    }
//                    @Override
//                    public void onReadMessage(RetryTcpClient client, ChannelHandlerContext ctx, Object msg) {
//
//                        byte[] data = null;
//
//                        ByteBuf buf = (ByteBuf)msg;
////                        int len = buf.getUnsignedShort(2);
////
////                        try {
////                            data  = ees3DecodeECB(desKey, ByteBufUtil.getBytes(buf, buf.readerIndex()+19, len-21));
////                        } catch (Exception e) {
////                            e.printStackTrace();
////                        }
////
////                        buf.setBytes(buf.readerIndex() + 19, data);
//
//                        log.info("recv: {}", ByteBufUtil.hexDump(buf));
//                    }
//                    @Override
//                    public void onWriteMessageComplete(RetryTcpClient client, RetryTcpClient.Message msg) {
//                        log.info("write message complete");
//                    }
//                })
//                .build();
//
//        new Thread(() -> {
//            while (!client.isClosed()) {
//
//                if(!client.isWritable()) {
//                    try {
//                        Thread.sleep(100);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    continue;
//                }
//
//                RetryTcpClient.Message message = store.peek();
//                if(message == null) {
//                    try {
//                        Thread.sleep(100);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    continue;
//                }
//
//                ChannelFuture future = client.send(message);
//
//                if(future != null) {
//                    try {
//                        // 发送成功,将消息从队列中删除
//                        future.get();
//                        store.dequeue();
//                    } catch (InterruptedException | ExecutionException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }).start();
//
//        while (true) {
//            String line = scanner.nextLine().replaceAll("\\s+", "");
//            if(!line.isEmpty()) {
//                if(line.equals("quit")) {
//                    client.close();
//                    break;
//                } else {
//                    log.info("send: {}", line);
//                    store.enqueue(new RetryTcpClient.ByteBufMessage(Unpooled.wrappedBuffer(hexStringToByteArray(line))));
////                    client.send(new RetryTcpClient.ByteBufMessage(Unpooled.wrappedBuffer(hexStringToByteArray(line))));
//                }
//            }
//        }
    }


}
